/* Filename: dup.c
 * Description: 6.dup,dup2和原子操作
 *     把puts("hello");不输出到标准输出而是存入到/tmp/out
 * Last modified: humble 20200119 22:56
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FILENAME "/tmp/out"

int main(int argc, char **argv) {
    int fd = open(FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600);
    if(fd < 0){ fprintf(stderr, "open %s failed", FILENAME); exit(1); }

    /* 以下两步非原子操作，别的线程也在打开关闭文件，就发生了竞争 */
    //如果fd本身就是1，那么close(1)再dup(fd)就没意义了
    //close(1); //此时最小可用的是1
    //dup(fd); //把fd拷贝到当前最小可用的描述符(也就是1)，前后两个描述服都指向同一个结构体
    //close(fd);

    dup2(fd,1); // 若fd==1则不处理；若1被占用会自动close(1)，然后把fd拷贝到1
    if(fd != 1){ close(fd); } // 必须做判断不等于1
    /************************/
    puts("hello"); // 输出到1
    /* 因为前面close(1)了，记得open回来，还原现场 */
    return 0;
}
